<template>
  <div id="mapContainer">
    <div class="panel">
      <el-button @click="addRiver_manualBbox">视口裁剪</el-button>
      <el-button @click="addRiver_canvas">canvas渲染</el-button>
    </div>

    <ActivePanel
      title="时间轴"
      :position="{
        top: '500px',
        left: '10px',
      }">
      <div class="time-bar">
        <div :class="{ 'show-index': true, active: isPlaying }">
          {{ timeIndex }}
        </div>
        <el-button @click="go">前进</el-button>
        <el-button @click="back">后退</el-button>
        <el-button @click="reset">重置</el-button>
        <el-button @click="play">播放</el-button>
        <el-button @click="pause">暂停</el-button>
      </div>
    </ActivePanel>
  </div>
</template>
<script setup>
import { Map, View } from "ol";
import { fromLonLat, get, transform } from "ol/proj";
import { containsCoordinate, containsExtent } from "ol/extent";

import {
  Tile as TileLayer,
  Vector as VectorLayer,
  Image as ImageLayer,
} from "ol/layer";
import { Vector as VectorSource, ImageCanvas } from "ol/source";
import Feature from "ol/feature";
import { Point, LineString, Polygon, Circle } from "ol/geom";
import {
  Style,
  Stroke,
  Fill,
  Circle as CircleStyle,
  Icon,
  Text,
} from "ol/style";

import GeoJSON from "ol/format/GeoJSON.js";

import { bbox as bboxStrategy } from "ol/loadingstrategy";

import { register } from "ol/proj/proj4";
import proj4 from "proj4";

import * as turf from "@turf/turf";
import * as radash from "radash";

import { onMounted, nextTick, ref, watchEffect, watch } from "vue";

import { tdt_api_key /** 天地图的key */ } from "@/config/keys.json";
import { addTdtBaseLayer } from "@/utils/baseMap.js";

import { getLayerByName, getVectorLayer } from "@/utils/layer.js";
import { flyTo, flyToFeature, getExtent } from "../../utils/view";

import ActivePanel from "@/components/ActivePanel.vue";

import BJGrid from "@/assets/geojson/BJ.json";

const timeIndex = ref(0);
const timer = ref(null);
const interval = 3000;
const isPlaying = ref(false);

function initMap() {
  proj4.defs(
    "EPSG:4547",
    "+proj=tmerc +lat_0=0 +lon_0=114 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs +type=crs"
  );
  register(proj4);
  const map = new Map({
    view: new View({
      projection: "EPSG:4326",
      center: [113.17756338652154, 23.701191837626297],
      zoom: 12,
      constrainResolution: true,
    }),
    target: "mapContainer",
    controls: [],
  });

  // 加载底图
  addTdtBaseLayer(map, tdt_api_key, "img", "c", "wmts");
  window.map = map;

  map.on("click", e => {
    console.log("click", e.coordinate);
  });
}

onMounted(() => {
  nextTick(() => {
    initMap();
  });
});

let hydrody1DFeatures, hydrody1DLayer;
async function addRiver() {
  //   addRiver_normal();
  addRiver_manualBbox();
}

// 普通正常加载
function addRiver_normal() {
  hydrody1DLayer = new VectorLayer({
    source: new VectorSource({
      format: new GeoJSON({
        dataProjection: "EPSG:4547",
        featureProjection: "EPSG:4326",
      }),
      url: "src/assets/geojson/BJ.json",
      //   strategy: bboxStrategy, // 使用 bbox 策略
    }),
  });

  window.map.addLayer(hydrody1DLayer);
}

// 按需要加载（只加载视口内的要素）
function addRiver_bbox() {
  hydrody1DLayer = new VectorLayer({
    source: new VectorSource({
      format: new GeoJSON({
        dataProjection: "EPSG:4547",
        featureProjection: "EPSG:4326",
      }),
      url: "src/assets/geojson/BJ.json",
      strategy: bboxStrategy, // 使用 bbox 策略
    }),
  });

  window.map.addLayer(hydrody1DLayer);
}

// 手动实现视口裁剪
function addRiver_manualBbox() {
  // 创建矢量图层
  hydrody1DLayer = new VectorLayer({
    source: new VectorSource({}),
  });

  // 将矢量图层添加到地图
  window.map.addLayer(hydrody1DLayer);

  // 读取GeoJSON数据
  hydrody1DFeatures = new GeoJSON().readFeatures(BJGrid, {
    dataProjection: "EPSG:4547",
    featureProjection: "EPSG:4326",
  });

  // 过滤出在视口内的要素
  const featuresInView = filterFeaturesInView();

  // 清空原有要素，添加在视口内的要素
  const source = hydrody1DLayer.getSource();
  source.clear();
  source.addFeatures(featuresInView);

  // 监听地图移动事件(当视口变化时，重新过滤要素)
  window.map.on("moveend", radash.debounce({ delay: 2000 }, onMoveEnd)); //使用了防抖，以减少不必要的计算
}

// canvas渲染
function addRiver_canvas() {
  // 创建矢量图层
  // const vectorLayer = getVectorLayer(window.map, "riverLayer");

  // 禁止矢量图层渲染
  // vectorLayer.setVisible(false);

  // 读取GeoJSON数据
  hydrody1DFeatures = new GeoJSON().readFeatures(BJGrid, {
    dataProjection: "EPSG:4547",
    featureProjection: "EPSG:4326",
  });

  // vectorLayer.getSource().addFeatures(hydrody1DFeatures);

  // 获取地图的像素尺寸
  const mapSize = window.map.getSize();


  // 使用canvas渲染
  const imageLayer = new ImageLayer({
    properties: {
      name: "canvasRiverLayer",
    },
    zIndex: 99999,
    source: new ImageCanvas({
      canvasFunction: (
        _extent,
        _resolution,
        _pixelRatio,
        size,
        _projection
      ) => {
        // 创建画布
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");

        // 设置画布大小
        canvas.width = size[0];
        canvas.height = size[1];

        // 计算缩放比例
        const ratio = mapSize[0] / size[0];
        // 设置字体
        ctx.font = "60px Arial";


        const features = hydrody1DFeatures;

        // 遍历要素，绘制
        features.forEach(feature => {
          // 每个格子设置颜色
          const color = feature.get("color") || "#00008B";

          // 几何要素
          let coordinates = feature.getGeometry().getCoordinates()[0][0];


          // 开始绘制路径
          ctx.beginPath();
          // 遍历环中的每个点并绘制格子
          let pixel = [0, 0];

          coordinates.forEach((point, index) => {
            // 未转比例的坐标
            const unconvertPixel = window.map.getPixelFromCoordinate(point);
            // 转比例坐标
            pixel = [unconvertPixel[0] / ratio, unconvertPixel[1] / ratio];
            if (index === 0) {
              // 将绘制起点移动到第一个点
              ctx.moveTo(pixel[0], pixel[1]);
            } else if (index === coordinates.length - 1) {
              // 绘制闭合路径
              ctx.closePath();
            } else {
              // 绘制线段到下一个点
              ctx.lineTo(pixel[0], pixel[1]);
            }
          });

          ctx.fillStyle = "red";
          ctx.fill();
          // ctx.strokeStyle = "black";
          // ctx.lineWidth = 1;
          // ctx.stroke();
        });

        return canvas;
      },
      projection: "EPSG:4326",
      ratio: 1,
    }),
  });

  window.map.addLayer(imageLayer);

}

function onMoveEnd() {
  const featuresInView = filterFeaturesInView();
  const source = hydrody1DLayer.getSource();

  source.clear();
  source.addFeatures(featuresInView);
}

// 过滤出在视口内的要素
function filterFeaturesInView() {
  const viewExtent = getExtent(window.map);

  const featuresInView = hydrody1DFeatures.filter(feature => {
    const polygonExtent = feature.getGeometry().getExtent();
    return containsExtent(viewExtent, polygonExtent);
  });

  console.log("filterFeaturesInView", featuresInView.length);

  return featuresInView;
}

// 更新河道颜色
const colorBand = [
  "#ff0000",
  "#ff7f00",
  "#ffff00",
  "#7fff00",
  "#00ff00",
  "#00ff7f",
  "#00ffff",
  "#007fff",
  "#0000ff",
  "#7f00ff",
  "#ff00ff",
  "#ff007f",
];
function upDateRiver(index) {
  //   if (!hydrody1DLayer && !hydrody1DFeatures) return;
  //   const color = colorBand[index % 12];
  hydrody1DFeatures.forEach((feature, i) => {
    const color = colorBand[radash.random(0, 11)];

    feature.setStyle(
      new Style({
        stroke: new Stroke({
          color: color,
          width: 1,
        }),
        fill: new Fill({
          color,
        }),
      })
    );
  });

  //   hydrody1DLayer.setStyle(
  //     new Style({
  //       stroke: new Stroke({
  //         color: color,
  //         width: 1,
  //       }),
  //       fill: new Fill({
  //         color,
  //       }),
  //     })
  //   );
}

watch(timeIndex, () => {
  upDateRiver(timeIndex.value);
});

// 时间轴
function go() {
  timeIndex.value++;
}

function back() {
  if (timeIndex.value > 0) {
    timeIndex.value--;
  }
}

function reset() {
  timeIndex.value = 0;
}

function play() {
  isPlaying.value = true;
  timer.value = setInterval(() => {
    timeIndex.value++;
  }, interval);
}

function pause() {
  isPlaying.value = false;
  clearInterval(timer.value);
}
</script>

<style lang="less" scoped>
#mapContainer {
  width: 100%;
  height: 99vh;
}

.panel {
  position: absolute;
  top: 10px;
  left: 150px;
  z-index: 999;
}

.time-bar {
  .show-index {
    margin: 10px, 0;

    font-weight: bold;
    font-size: 20px;
    color: red;
    &.active {
      color: green;
    }
  }
}
</style>
